添加依赖
Spring Security是后台开发中经常使用的身份认证和访问权限控制框架,集成起来十分简单,对Restful接口的支持也比较完备,至于更多的介绍,可以参考 Spring Security 参考手册,在pom.xml中添加依赖如下:
1 | <dependency> |
JWT(Json Web Token)定义了一种简洁的,自包含的信息传递规范,在目前前后端分离的架构环境下使用十分频繁,但JWT也存在一定的局限性,在具体的业务场景下通常无法直接代替通常意义上的session,带着学习的目的,我们可以尝试一下简单的使用,详细介绍可以参考 JWT介绍,在pom.xml中添加依赖如下:
1 | <dependency> |
配置
JWT
JWT的配置相对来讲是比较简单的,主要包括两个部分:1.定义JWT属性,用于从配置文件读取配置信息;2.定义Token生成和解析的方法;3.定义Token验证过滤器。话不多说,直接贴代码:
- 定义JWT属性
1 |
|
- 定义Token生成和解析的方法
1 | public class JwtUtil { |
- 定义Token验证过滤器
1 | public class JwtAuthenticationFiler extends OncePerRequestFilter { |
OK,JWT的简单配置就完成了,这里只是对JWT的简单使用,在通常的开发中还需要更复杂的处理逻辑,比如通常的访问Token,刷新Token等,这里就不详细说了。
Security
- 修改数据库
首先,修改一下数据库表结构,修改之后共有用户表、角色表、用户角色关系表,ER图如下:
角色表里共有两条数据,这两个角色是我们后续进行访问权限控制的基础,如下所示:
- 修改User类,实现UserDetails接口
UserDetails是Security提供的一个接口,其中定义了一系列用于判断User状态和权限的方法,User实体如下所示:
1 | public class User implements Serializable, UserDetails { |
- 修改UserService类,实现UserDetailsService接口
这里需要实现UserDetailsService中的loadUserByUsername方法,在这个方法中根据Username查询用户,然后交由Security去匹配用户名和密码(如果需要复杂的用户验证逻辑,可以重写UsernamePasswordAuthenticationFilter,然后将重写的过滤器添加到Security的过滤器链中),UserService代码如下所示:
1 |
|
- 定义Handler和EntryPoint
因为我们的种子项目是以Restful接口形式提供服务的,所以我们不需要进行页面跳转,而是需要定义一系列的处理器,共包括登录成功、登录失败、注销成功、权限认证这四个处理器,这里就不把代码全部贴出来了。
需要值得注意的是:Security是通过一系列过滤器组成的过滤器链来进行权限控制的,当未登录的用户访问了受权限保护的资源时,会抛出AuthenticationException,默认由LoginUrlAuthenticationEntryPoint处理,也就是默认跳转至登录页面,显然我们需要的是为用户返回一个合理的提示,那么就需要自定义一个处理器处理AuthenticationException,代码如下:
1 | /** |
下面为登录失败的handler代码,在这里只简单返回了错误提示:
1 | /** |
- 自定义加密方式
通常用户密码是要加密存储的,因此我们需要告知Security我们使用了何种加密方式,我们可以通过实现PasswordEncoder接口来实现加密和认证,本例采用简单的MD5加密,如下所示:
1 | public class CustomPasswordEncoder implements PasswordEncoder { |
- Security配置类
1 |
|
到这里,Security就配置完了,虽然看起来配置很多,但其实使用起来是非常灵活的。
异常处理
良好的错误提醒能够极大地提高用户体验,在前后端分离的架构下,前端和后端通常需要确定一套错误提示方案,这时就需要对异常进行统一的处理。
异常处理按我的理解可以分为两种:其一,业务异常处理;其二,全局异常处理。
- 业务异常处理
这里所说的业务异常处理是指处理在业务处理过程中抛出的异常,比如我们在Controller中抛出异常。对于这些异常,Spring为我们提供了很好的处理方式,我们可以通过@ControllerAdvice注解定义异常处理类,配合@EceptionHandler注解定义异常处理方法,来捕获在Controller中抛出的异常,代码如下:
1 |
|
在这里我们根据业务需要配置不同的异常处理方法。
- 全局异常处理
除了在Controller中抛出的异常,我们通常还会遇到404等异常,SpringBoot为我们提供了一个默认的异常处理方式:即将错误映射至/error路径,想进一步了解可以参考:
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController。
1 | /** |
总结
经过以上的配置,我们就完成了简单的访问权限控制和Token认证了,并添加了简单的异常处理,让我们的应用具有更好、更完善的错误提示和更安全的访问控制。
最近在查看JWT资料的时候发现了一篇驳斥JWT自包含、无状态的文章,感觉写的很有道理,推荐给大家 讲真,别再使用JWT了!
虽然JWT在分布式应用和客户端程序中有很大的便利条件,但也确实存在一些问题使它无法绕过后台缓存状态这一问题,当然,具体的业务场景对应不同的使用方式,最终还是取决于是否适用于业务场景。
源码地址:https://github.com/GreedyStar/spring-boot-demo
最后的最后,安利一下自己写的一个Java代码生成工具,能够方便的生成Spring、SpringMVC、Mybatis架构下的Java代码,希望能对大家有所帮助,地址:Java代码生成器:Generator